package br.com.hs.nfe.common.validation;

import br.com.hs.nfe.common.anotation.Node;
import br.com.hs.nfe.common.app.AppConfig;
import br.com.hs.nfe.common.enumeration.*;
import br.com.hs.nfe.common.to.*;
import br.com.hs.nfe.common.util.*;
import br.com.hs.nfe.common.validation.NotaFiscalValidation;
import br.com.hs.nfe.common.validation.Validable;
import br.com.hs.nfe.common.validation.ValidadorAnotacoes;
import br.com.hs.nfe.common.validation.ValidadorDocumento;
import br.com.hs.nfe.common.validation.exception.HSValidationException;
import br.com.hs.nfe.util.UtilHelper;
import br.inf.portalfiscal.nfe.*;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.Date;

/**
 * Classe com as regras de valicação da NF-e.
 * @author Ranlive Hrysyk
 */
public class ValidadorNotaFiscal {

    private String className;
    private static final double DOUBLE_FORMAT = 1.0D;

    /**
     * Validar as regras de negócio na NF-e.
     */
    public void validarNotaFiscalTO(NotaFiscalTO notaFiscalTO, NFeDocument nFeDocument) throws HSValidationException {
        try {
            className = MessageFormat.format(HSConstants.APP_CLASS_NAME, new Object[]{notaFiscalTO.getClass().getAnnotation(Node.class).name()});
            //Validar máximo bytes
            validarMaximoBytes(notaFiscalTO);
            //Obtém os dados da nota
            TNFe.InfNFe.Ide ide = nFeDocument.getNFe().getInfNFe().getIde();
            if (ide == null) {
                adicionarErro(HSMessageConstants.INFNFE_IDE_OBRIGATORIA, notaFiscalTO);
            } else {
                validarID(nFeDocument, notaFiscalTO);
                validarIDE(nFeDocument, notaFiscalTO);
                validarEmitente(nFeDocument, notaFiscalTO);
                validarAvulsa(nFeDocument, notaFiscalTO);
                validarDestinatario(nFeDocument, notaFiscalTO);
//                validarRetirada(doc, notaFiscalTO);
//                validarEntrega(doc, notaFiscalTO);
                validarProdutos(nFeDocument, notaFiscalTO);
                validarTransporte(nFeDocument, notaFiscalTO);
            }
        } catch (Exception ex) {
            throw new HSValidationException(ex);
        }
    }

    /**
     * Valida o tamanho máximo do arquivo da NF-e.
     */
    private void validarMaximoBytes(NotaFiscalTO notaFiscalTO) {
        if (!NotaFiscalValidation.getInstance().validarMaximoBytes(notaFiscalTO.getXmlString())) {
            adicionarErro(HSMessageConstants.MSG_NOTA_FISCAL_MAXIMO_BYTES, notaFiscalTO);
        }
    }

    /**
     * Valida o ID da NF-e.
     */
    private void validarID(NFeDocument nFeDocument, NotaFiscalTO notaFiscalTO) {
        String id = nFeDocument.getNFe().getInfNFe().getId();
        String chaveAcesso = ChaveAcessoHelper.gerarChaveAcesso(notaFiscalTO);
        if ((StringHelper.isBlankOrNull(id)) || (id.length() != 47) || (!id.substring(0, 3).equals("NFe")) || (!id.substring(3, 47).equals(chaveAcesso))) {
            adicionarErro(MessageFormat.format(HSMessageConstants.INFNFE_DADOSNFE_ID_INVALIDO, new Object[]{id}), notaFiscalTO);
        }
    }

    /**
     * Valida o nó Ide.
     */
    private void validarIDE(NFeDocument nFeDocument, NotaFiscalTO notaFiscalTO) throws HSValidationException {
        try {
            TNFe.InfNFe.Ide ide = nFeDocument.getNFe().getInfNFe().getIde();
            TNFe.InfNFe.Emit emitente = nFeDocument.getNFe().getInfNFe().getEmit();

            //Valida os campos da nota Fiscal
            ValidadorAnotacoes.validate(notaFiscalTO);

            //Valida a série e com o tipo de emissão e a entrada em contingência
            if (!StringHelper.isBlankOrNull(ide.getTpEmis())) {
                if (TNFe.InfNFe.Ide.TpEmis.X_3.equals(ide.getTpEmis())) {
                    if ((StringHelper.isBlankOrNull(ide.getSerie())) || (Integer.parseInt(ide.getSerie()) < 900) || (Integer.parseInt(ide.getSerie()) > 999)) {
                        adicionarErro(MessageFormat.format(HSMessageConstants.INFNFE_IDE_SERIE_SCAN_INVALIDA, new Object[]{ide.getSerie(), "{900-999}"}), notaFiscalTO);
                    }
                } else {
                    if ((nFeDocument.getNFe().getInfNFe().getAvulsa() == null) && ((StringHelper.isBlankOrNull(ide.getSerie())) || (Integer.parseInt(ide.getSerie()) < 0) || (Integer.parseInt(ide.getSerie()) > 889))) {
                        adicionarErro(MessageFormat.format(HSMessageConstants.INFNFE_IDE_SERIE_SEFAZ_INVALIDA, new Object[]{ide.getSerie(), "{0-889}"}), notaFiscalTO);
                    }
                    if ((nFeDocument.getNFe().getInfNFe().getAvulsa() != null) && ((StringHelper.isBlankOrNull(ide.getSerie())) || (Integer.parseInt(ide.getSerie()) < 890) || (Integer.parseInt(ide.getSerie()) > 899))) {
                        adicionarErro(MessageFormat.format(HSMessageConstants.INFNFE_IDE_SERIE_SEFAZ_INVALIDA, new Object[]{ide.getSerie(), "{890-899}"}), notaFiscalTO);
                    }
                }
            }

            //Valida a data de emissão
            if ((!StringHelper.isBlankOrNull(ide.getTpNF())) && (TNFe.InfNFe.Ide.TpNF.X_1.equals(ide.getTpNF())) && (!StringHelper.isBlankOrNull(ide.getDSaiEnt())) && (DateHelper.getDate(ide.getDSaiEnt(), DateHelper.DATE_XML_FORMAT).compareTo(DateHelper.getDate(ide.getDEmi(), DateHelper.DATE_XML_FORMAT)) < 0)) {
                adicionarErro(MessageFormat.format(HSMessageConstants.INFNFE_IDE_DTSAIDA_MENOR_DTEMISSAO, new Object[]{DateHelper.formatarData(DateHelper.getDate(ide.getDSaiEnt(), DateHelper.DATE_XML_FORMAT)), DateHelper.formatarData(DateHelper.getDate(ide.getDEmi(), DateHelper.DATE_XML_FORMAT))}), notaFiscalTO);
            }
            if ((StringHelper.isBlankOrNull(ide.getDEmi())) || (DateHelper.getDaysBetweenDates(new Date(), DateHelper.getDate(ide.getDEmi(), DateHelper.DATE_XML_FORMAT)) > 30L)) {
                adicionarErro(MessageFormat.format(HSMessageConstants.INFNFE_IDE_DTEMISSAO_30_DIAS, new Object[]{DateHelper.formatarData(DateHelper.getDate(ide.getDEmi(), DateHelper.DATE_XML_FORMAT))}), notaFiscalTO);
            }

            //Valida o código do munípio gerador
            String siglaUF = StringHelper.isBlankOrNull(emitente.getEnderEmit().getUF()) ? null : emitente.getEnderEmit().getUF().toString();
            String xMun = StringHelper.isBlankOrNull(ide.getCMunFG()) ? null : ide.getCMunFG();
            if ((StringHelper.isBlankOrNull(ide.getCMunFG())) || (StringHelper.isBlankOrNull(emitente.getEnderEmit().getUF())) || (!UtilHelper.getInstance().validarMunicipioByUF(ide.getCMunFG(), emitente.getEnderEmit().getUF().toString()))) {
                adicionarErro(MessageFormat.format(HSMessageConstants.INFNFE_IDE_CDMUN_FTGERADOR_DIFER_UFEMIT, new Object[]{xMun, siglaUF}), notaFiscalTO);
            }

            //Valida a justificativa de entrada em contingência
            if (!StringHelper.isBlankOrNull(ide.getTpEmis())) {
                if ((TNFe.InfNFe.Ide.TpEmis.X_1.equals(ide.getTpEmis())) && (!StringHelper.isBlankOrNull(ide.getXJust()))) {
                    adicionarErro(HSMessageConstants.INFNFE_IDE_JUST_INFORMADA_EMISSAO_NORMAL, notaFiscalTO);
                }
                if ((!TNFe.InfNFe.Ide.TpEmis.X_1.equals(ide.getTpEmis())) && (StringHelper.isBlankOrNull(ide.getXJust()))) {
                    adicionarErro(HSMessageConstants.INFNFE_IDE_JUST_NAO_INFORMADA, notaFiscalTO);
                }
            }

            //Validar digito da chave de acesso
            if ((StringHelper.isBlankOrNull(ide.getCDV())) || (!ChaveAcessoHelper.gerarDigitoChaveAcesso(notaFiscalTO).equals(ide.getCDV()))) {
                adicionarErro(HSMessageConstants.INFNFE_IDE_NFE_CHAVE_ACESSO_INVALIDA, notaFiscalTO);
            }


            //Validar tipo ambiente
            TipoAmbienteEnum tipoAmbiente = null;
            if (!StringHelper.isBlankOrNull(ide.getTpAmb())) {
                if (TAmb.X_1.equals(ide.getTpAmb())) {
                    tipoAmbiente = TipoAmbienteEnum.PRODUCAO;
                } else {
                    tipoAmbiente = TipoAmbienteEnum.HOMOLOGACAO;
                }
            }
            if ((tipoAmbiente == null) || (!tipoAmbiente.getCodigo().equals(AppConfig.getInstance().getTipoAmbiente()))) {
                adicionarErro(HSMessageConstants.INFNFE_IDE_NFE_AMBIENTE_DIFERENTE, notaFiscalTO);
            }

            //Validar notas fiscais referenciadas
            String cnpjEmitenteNFREf = null;
            if ((ide.getNFrefArray() != null) && (ide.getNFrefArray().length > 0)) {
                for (int i = 0; i < ide.getNFrefArray().length; i++) {
                    TNFe.InfNFe.Ide.NFref nfRef = ide.getNFrefArray(i);

                    if (!StringHelper.isBlankOrNull(nfRef.getRefNFe())) {
                        cnpjEmitenteNFREf = nfRef.getRefNFe().substring(6, 20);
                        if (!ChaveAcessoHelper.verificarDigitoChaveAcesso(nfRef.getRefNFe())) {
                            adicionarErro(MessageFormat.format(HSMessageConstants.INFNFE_IDE_DIGITOVERIF_NFEREF_INVALIDO, new Object[]{nfRef.getRefNFe()}), notaFiscalTO);
                        }
                    }
                    if ((!StringHelper.isBlankOrNull(nfRef.getRefCTe())) && (!ChaveAcessoHelper.verificarDigitoChaveAcesso(nfRef.getRefCTe()))) {
                        adicionarErro(MessageFormat.format(HSMessageConstants.INFNFE_IDE_DIGITO_CHAVEACESSO_CTE_INVALIDO, new Object[]{nfRef.getRefCTe()}), notaFiscalTO);
                    }
                }
            }

            //Validar tipo de emissão nota fiscal complementar
            if ((!StringHelper.isBlankOrNull(ide.getFinNFe())) && (TFinNFe.X_2.equals(ide.getFinNFe()))) {
                int contNFRef = 0;
                for (int i = 0; i < ide.getNFrefArray().length; i++) {
                    TNFe.InfNFe.Ide.NFref nfRef = ide.getNFrefArray(i);
                    if ((nfRef.getRefNF() != null) || (nfRef.getRefNFe() != null)) {
                        contNFRef++;
                    }
                }
                if (contNFRef == 0) {
                    adicionarErro(HSMessageConstants.INFNFE_IDE_NFE_COMPLEMENTAR_SEM_NFREF, notaFiscalTO);
                } else if (contNFRef > 1) {
                    adicionarErro(HSMessageConstants.INFNFE_IDE_NFE_COMPLEMENTAR_POSSUI_MAIS1_NFREF, notaFiscalTO);
                } else if ((StringHelper.isBlankOrNull(cnpjEmitenteNFREf)) || ((!StringHelper.isBlankOrNull(emitente.getCNPJ())) && (!cnpjEmitenteNFREf.equals(emitente.getCNPJ())))) {
                    adicionarErro(MessageFormat.format(HSMessageConstants.INFNFE_IDE_NFE_COMPLEMENTAR_CNPJ_DIFERENTE, new Object[]{cnpjEmitenteNFREf, emitente.getCNPJ()}), notaFiscalTO);
                }
            }

            //Validar processo emissão
            if ((StringHelper.isBlankOrNull(ide.getProcEmi())) || ((!TProcEmi.X_0.equals(ide.getProcEmi())) && (!TProcEmi.X_3.equals(ide.getProcEmi())))) {
                adicionarErro(MessageFormat.format(HSMessageConstants.INFNFE_IDE_NFE_PROCEMI_NAOCONTRIBUINTE, new Object[]{cnpjEmitenteNFREf, emitente.getCNPJ()}), notaFiscalTO);
            }
        } catch (Exception ex) {
            throw new HSValidationException(ex);
        }
    }

    /**
     * Valida o emitente da NF-e.
     */
    private void validarEmitente(NFeDocument nfeDocument, NotaFiscalTO notaFiscalTO) throws HSValidationException {
        try {
            TNFe.InfNFe.Ide ide = nfeDocument.getNFe().getInfNFe().getIde();
            TNFe.InfNFe.Emit emitente = nfeDocument.getNFe().getInfNFe().getEmit();
            String classNameEmitente = getClassName(EmitenteTO.class);

            validarAnotacoes(notaFiscalTO.getEmitenteTO(), notaFiscalTO);

            //Valida o preenchimento do campo data e hora de entrada em contingência
            if (ide.getTpEmis() != null) {
                if (!TNFe.InfNFe.Ide.TpEmis.X_1.equals(ide.getTpEmis())) {
                    if (StringHelper.isBlankOrNull(ide.getDhCont())) {
                        adicionarErro(HSMessageConstants.INFNFE_IDE_DHCONT_NAO_INFORMADO, notaFiscalTO);
                    } else if ((!StringHelper.isBlankOrNull(ide.getDEmi())) && (DateHelper.getDate(ide.getDhCont(), DateHelper.DATE_XML_FORMAT).compareTo(DateHelper.getDate(ide.getDEmi(), DateHelper.DATE_XML_FORMAT)) > 0)) {
                        adicionarErro(MessageFormat.format(HSMessageConstants.INFNFE_EMITENTE_DTENTRADA_CONTING_MAIOR_DTEMISSAO, new Object[]{DateHelper.formatarData(DateHelper.getDate(ide.getDhCont(), DateHelper.DATE_XML_FORMAT)), DateHelper.formatarData(DateHelper.getDate(ide.getDEmi(), DateHelper.DATE_XML_FORMAT))}), notaFiscalTO);
                    }
                }
                if ((TNFe.InfNFe.Ide.TpEmis.X_1.equals(ide.getTpEmis())) && (!StringHelper.isBlankOrNull(ide.getDhCont()))) {
                    adicionarErro(HSMessageConstants.INFNFE_IDE_DHCONT_INFORMADO_EMISSAO_NORMAL, notaFiscalTO);
                }
            }

            if (emitente != null) {
                //Valida o preenchimento do campo CPF
                if ((emitente.getCPF() != null) && (nfeDocument.getNFe().getInfNFe().getAvulsa() == null)) {
                    adicionarErro(classNameEmitente + HSMessageConstants.INFNFE_EMITENTE_CPF_INFORMADO_NFE_NAO_AVULSA, notaFiscalTO);
                }

                //Valida o código do emitente
                String siglaUF = null;
                if (emitente.getEnderEmit() != null) {
                    siglaUF = StringHelper.isBlankOrNull(emitente.getEnderEmit().getUF()) ? null : emitente.getEnderEmit().getUF().toString();
                    String xMun = StringHelper.isBlankOrNull(emitente.getEnderEmit().getCMun()) ? null : emitente.getEnderEmit().getCMun();
                    if ((StringHelper.isBlankOrNull(emitente.getEnderEmit().getCMun())) || (StringHelper.isBlankOrNull(emitente.getEnderEmit().getUF())) || (!UtilHelper.getInstance().validarMunicipioByUF(emitente.getEnderEmit().getCMun(), emitente.getEnderEmit().getUF().toString()))) {
                        adicionarErro(classNameEmitente + MessageFormat.format(HSMessageConstants.INFNFE_EMITENTE_CDMUN_EMITENTE_DIFER_UFEMIT, new Object[]{xMun, siglaUF}), notaFiscalTO);
                    }
                }

                //Valida inscrições estaduais
                UFEnum uf = UFEnum.getEnumByUF(siglaUF);
                if ((!StringHelper.isBlankOrNull(emitente.getIE())) && (!ValidadorDocumento.validateIE(emitente.getIE(), uf))) {
                    adicionarErro(classNameEmitente + HSMessageConstants.INFNFE_EMITENTE_IE_INVALIDA, notaFiscalTO);
                }
                if ((!StringHelper.isBlankOrNull(emitente.getIEST())) && (!ValidadorDocumento.validateIE(emitente.getIEST(), uf))) {
                    adicionarErro(classNameEmitente + HSMessageConstants.INFNFE_EMITENTE_IEST_INVALIDA, notaFiscalTO);
                }
            }
        } catch (Exception ex) {
            throw new HSValidationException(ex.getMessage(), ex);
        }
    }

    /**
     * Valida o preenchimento da Avulsa
     */
    private void validarAvulsa(NFeDocument nfeDocument, NotaFiscalTO notaFiscalTO) {
        TNFe.InfNFe.Avulsa avulsa = nfeDocument.getNFe().getInfNFe().getAvulsa();
        TNFe.InfNFe.Emit emit = nfeDocument.getNFe().getInfNFe().getEmit();
        if ((avulsa != null) && (StringHelper.isBlankOrNull(emit.getCPF()))) {
            adicionarErro(HSMessageConstants.INFNFE_IDENT_FISCO_EMITENTE_AVULSA, notaFiscalTO);
        }
    }

    /**
     * Validar cliente/destinatário  da NF-e.
     */
    private void validarDestinatario(NFeDocument nfeDocument, NotaFiscalTO notaFiscalTO) throws HSValidationException {
        try {
            TNFe.InfNFe.Dest dest = nfeDocument.getNFe().getInfNFe().getDest();
            String classNameDest = getClassName(ClienteTO.class);

            validarAnotacoes(notaFiscalTO.getClienteTO(), notaFiscalTO);

            if (dest != null) {
                if (dest.getEnderDest() != null) {
                    if ((!StringHelper.isBlankOrNull(dest.getEnderDest().getUF())) && (TUf.EX.equals(dest.getEnderDest().getUF()))) {
                        if (!StringHelper.isBlankOrNull(dest.getCNPJ())) {
                            adicionarErro(classNameDest + HSMessageConstants.INFNFE_DEST_CNPJ_INFORMADO_EXTERIOR, notaFiscalTO);
                        }
                        if ((StringHelper.isBlankOrNull(dest.getEnderDest().getCMun())) || (!dest.getEnderDest().getCMun().equals(HSConstants.CODIGO_MUNICIPIO_EXTERIOR))) {
                            adicionarErro(classNameDest + HSMessageConstants.INFNFE_DEST_CMUN_DIFERENTE_9999999, notaFiscalTO);
                        }
                        if ((StringHelper.isBlankOrNull(dest.getEnderDest().getCPais())) || (Tpais.X_1058.equals(dest.getEnderDest().getCPais()))) {
                            adicionarErro(classNameDest + HSMessageConstants.INFNFE_DEST_CPAIS_INVALIDO_EXTERIOR, notaFiscalTO);
                        }
                        if (!StringHelper.isBlankOrNull(dest.getIE())) {
                            adicionarErro(classNameDest + MessageFormat.format(HSMessageConstants.INFNFE_DEST_IE_INVALIDA, new Object[]{dest.getIE()}), notaFiscalTO);
                        }
                    } else {
                        String siglaUF = StringHelper.isBlankOrNull(dest.getEnderDest().getUF()) ? null : dest.getEnderDest().getUF().toString();
                        String xMun = StringHelper.isBlankOrNull(dest.getEnderDest().getCMun()) ? null : dest.getEnderDest().getCMun();
                        if ((StringHelper.isBlankOrNull(dest.getCNPJ())) && (StringHelper.isBlankOrNull(dest.getCPF()))) {
                            adicionarErro(classNameDest + HSMessageConstants.INFNFE_DEST_CNPJ_CPF_NULO, notaFiscalTO);
                        }
                        if ((StringHelper.isBlankOrNull(dest.getEnderDest().getCMun())) || (StringHelper.isBlankOrNull(dest.getEnderDest().getUF())) || (!UtilHelper.getInstance().validarMunicipioByUF(dest.getEnderDest().getCMun(), dest.getEnderDest().getUF().toString()))) {
                            adicionarErro(classNameDest + MessageFormat.format(HSMessageConstants.INFNFE_DEST_CMUN_UF_INVALIDO, new Object[]{xMun, siglaUF}), notaFiscalTO);
                        }
                        if ((!StringHelper.isBlankOrNull(dest.getEnderDest().getCPais())) && (!Tpais.X_1058.equals(dest.getEnderDest().getCPais()))) {
                            adicionarErro(classNameDest + MessageFormat.format(HSMessageConstants.INFNFE_DEST_CPAIS_INVALIDO_NAO_EXTERIOR, new Object[]{dest.getEnderDest().getCPais()}), notaFiscalTO);
                        }
                        if ((!StringHelper.isBlankOrNull(dest.getIE())) && (!ValidadorDocumento.validateIE(dest.getIE(), UFEnum.getEnumByUF(siglaUF)))) {
                            adicionarErro(classNameDest + MessageFormat.format(HSMessageConstants.INFNFE_DEST_IE_INVALIDA, new Object[]{dest.getIE()}), notaFiscalTO);
                        }
                    }
                }
            }
        } catch (Exception ex) {
            throw new HSValidationException(ex.getMessage(), ex);
        }
    }

    /**
     * Valdalita os produtos.
     */
    private void validarProdutos(NFeDocument nfeDocument, NotaFiscalTO notaFiscalTO) throws HSValidationException {
        try {
            TNFe.InfNFe.Det[] det = nfeDocument.getNFe().getInfNFe().getDetArray();
            TNFe.InfNFe.Ide ide = nfeDocument.getNFe().getInfNFe().getIde();
            TNFe.InfNFe.Dest destinatario = nfeDocument.getNFe().getInfNFe().getDest();
            TNFe.InfNFe.Emit emitente = nfeDocument.getNFe().getInfNFe().getEmit();
            String classNameDet = getClassName(ProdutoNotaTO.class);


            if ((det != null) && (det.length > 0)) {
                double valorTotalBCICMS = 0.0D;
                double valorTotalBCICMSST = 0.0D;
                double valorTotalICMS = 0.0D;
                double valorTotalICMSST = 0.0D;
                double valorTotalProduto = 0.0D;
                double valorTotalFrete = 0.0D;
                double valorTotalSeguro = 0.0D;
                double valorTotalDesconto = 0.0D;
                double valorTotalIPI = 0.0D;

                boolean informadoGrupoICMS = false;
                boolean informadoGrupoISSQN = false;

                for (int i = 0; i < det.length; i++) {
                    TNFe.InfNFe.Det.Prod produto = det[i].getProd();
                    TNFe.InfNFe.Det.Imposto imposto = det[i].getImposto();

                    //Valida as anotações
                    if (notaFiscalTO.getListaProdutos() != null) {
                        ProdutoTO produtoTO = (ProdutoTO) notaFiscalTO.getListaProdutos().get(i).getProduto().clone();
                        ValidadorAnotacoes.validate(produtoTO);
                        if (produtoTO.hasValidationError()) {
                            for (String error : produtoTO.getValidationErrorList()) {
                                adicionarErro(classNameDet + error, notaFiscalTO);
                            }
                        }
                    }

                    if ((produto != null) && (produto.getCFOP() != null)) {
                        if (ide.getTpNF() != null) {
                            if (TNFe.InfNFe.Ide.TpNF.X_1.equals(ide.getTpNF())) {
                                if ((produto.getCFOP().toString().startsWith("1")) || (produto.getCFOP().toString().startsWith("2")) || (produto.getCFOP().toString().startsWith("3"))) {
                                    adicionarErro(classNameDet + MessageFormat.format(HSMessageConstants.INFNFE_PRODSERV_CFOP_ENTRADA_NOTASAIDA, new Object[]{produto.getCFOP().toString()}), notaFiscalTO);
                                }
                            } else if (TNFe.InfNFe.Ide.TpNF.X_0.equals(ide.getTpNF())) {
                                if ((produto.getCFOP().toString().startsWith("5")) || (produto.getCFOP().toString().startsWith("6")) || (produto.getCFOP().toString().startsWith("7"))) {
                                    adicionarErro(classNameDet + MessageFormat.format(HSMessageConstants.INFNFE_PRODSERV_CFOP_SAIDA_NOTAENTRADA, new Object[]{produto.getCFOP().toString()}), notaFiscalTO);
                                }
                            }
                        }

                        if ((imposto.getPIS() == null) || ((imposto.getPIS().getPISAliq() == null) && (imposto.getPIS().getPISNT() == null) && (imposto.getPIS().getPISOutr() == null) && (imposto.getPIS().getPISQtde() == null))) {
                            adicionarErro(classNameDet + HSMessageConstants.INFNFE_PRODSERV_PIS_NAO_INFORMADO, notaFiscalTO);
                        }
                        if ((imposto.getCOFINS() == null) || ((imposto.getCOFINS().getCOFINSAliq() == null) && (imposto.getCOFINS().getCOFINSNT() == null) && (imposto.getCOFINS().getCOFINSOutr() == null) && (imposto.getCOFINS().getCOFINSQtde() == null))) {
                            adicionarErro(classNameDet + HSMessageConstants.INFNFE_PRODSERV_COFINS_NAO_INFORMADO, notaFiscalTO);
                        }
                        if (((imposto.getICMS() != null) || (imposto.getIPI() != null) || (imposto.getII() != null)) && (imposto.getISSQN() != null)) {
                            adicionarErro(classNameDet + HSMessageConstants.INFNFE_PRODSERV_INFORME_ICMS_OU_ISSQN, notaFiscalTO);
                        }

                        TNFe.InfNFe.Det.Prod.Comb comb = produto.getComb();
                        String ufConsumo;
                        if ((comb != null) && (comb.getUFCons() != null)) {
                            ufConsumo = UFEnum.getEnumByUF(comb.getUFCons().toString()).getUF();
                        } else {
                            ufConsumo = null;
                        }
                        if (destinatario.getEnderDest() != null) {
                            String siglaUF = StringHelper.isBlankOrNull(destinatario.getEnderDest().getUF()) ? null : destinatario.getEnderDest().getUF().toString();
                            if ((!StringHelper.isBlankOrNull(destinatario.getEnderDest().getUF())) && (produto.getCFOP() != null)) {
                                if (((produto.getCFOP().toString().startsWith("3")) || (produto.getCFOP().toString().startsWith("7"))) && (!TUf.EX.equals(destinatario.getEnderDest().getUF()))) {
                                    if ((ufConsumo == null) || (!"EX".equals(ufConsumo))) {
                                        adicionarErro(classNameDet + MessageFormat.format(HSMessageConstants.INFNFE_PRODSERV_CFOP_EXTERIOR_UFDIFER_EX, new Object[]{produto.getCFOP().toString(), siglaUF}), notaFiscalTO);
                                    }
                                }
                            }
                        }
                        if ((destinatario.getEnderDest() != null) && (emitente.getEnderEmit() != null) && (!StringHelper.isBlankOrNull(destinatario.getEnderDest().getUF())) && (!StringHelper.isBlankOrNull(emitente.getEnderEmit().getUF()))) {
                            String siglaUFEmitente = emitente.getEnderEmit().getUF().toString();
                            String siglaUFDestinatario = destinatario.getEnderDest().getUF().toString();

                            if ((!StringHelper.isBlankOrNull(destinatario.getIE())) && (!HSConstants.ISENTO.equals(destinatario.getIE()))) {
                                if (produto.getCFOP().toString().startsWith("5")) {
                                    if ((!siglaUFEmitente.equals(siglaUFDestinatario)) && ((ufConsumo == null) || (!siglaUFEmitente.equals(ufConsumo)))) {
                                        adicionarErro(classNameDet + MessageFormat.format(HSMessageConstants.INFNFE_PRODSERV_CFOP_ESTADUAL_UFEMITENTE_DIFER_UFDEST, new Object[]{produto.getCFOP().toString(), siglaUFEmitente, siglaUFDestinatario}), notaFiscalTO);
                                    }
                                } else if (produto.getCFOP().toString().startsWith("1")) {
                                    if ((!siglaUFEmitente.equals(siglaUFDestinatario)) && ((ufConsumo == null) || (!siglaUFEmitente.equals(ufConsumo)))) {
                                        adicionarErro(classNameDet + MessageFormat.format(HSMessageConstants.INFNFE_PRODSERV_CFOP_ESTADUAL_UFEMITENTE_DIFER_UFREMETENTE, new Object[]{produto.getCFOP().toString(), siglaUFEmitente, siglaUFDestinatario}), notaFiscalTO);
                                    }
                                }
                            }
                            if (((produto.getCFOP().toString().startsWith("2")) || (produto.getCFOP().toString().startsWith("6"))) && (siglaUFEmitente.equals(siglaUFDestinatario)) && ((ufConsumo == null) || (siglaUFEmitente.equals(ufConsumo))) && (!emitente.getCNPJ().equals(destinatario.getCNPJ()))) {
                                adicionarErro(classNameDet + MessageFormat.format(HSMessageConstants.INFNFE_PRODSERV_CFOP_NAOESTADUAL_UFEMITENTE_IGUAL_UFDEST, new Object[]{produto.getCFOP().toString(), siglaUFEmitente, siglaUFDestinatario}), notaFiscalTO);
                            }
                        }
                        if ((produto.getCFOP() != null) && ((produto.getCFOP().toString().startsWith("3")) || (produto.getCFOP().toString().startsWith("7")))) {
                            if (((StringHelper.isBlankOrNull(produto.getNCM())) || (produto.getNCM().trim().length() != 8)) && ((imposto.getISSQN() == null) || (imposto.getISSQN().getCSitTrib() == null) || (!"00".equals(produto.getNCM())))) {
                                adicionarErro(classNameDet + MessageFormat.format(HSMessageConstants.INFNFE_PRODSERV_CFOP_EXTERIOR_NCM_INVALIDO, new Object[]{produto.getCFOP().toString(), produto.getNCM()}), notaFiscalTO);
                            }
                            if ((produto.getCFOP().toString().startsWith("3")) && (!"3201".equals(produto.getCFOP().toString())) && (!"3202".equals(produto.getCFOP().toString())) && (!"3211".equals(produto.getCFOP().toString())) && (!"3503".equals(produto.getCFOP().toString())) && (!"3553".equals(produto.getCFOP().toString()))) {
                                if ((produto.getDIArray() == null) || (produto.getDIArray().length == 0)) {
                                    adicionarErro(classNameDet + MessageFormat.format(HSMessageConstants.INFNFE_PRODSERV_CFOP_IMPORTACAO_DI_INVALIDO, new Object[]{produto.getCFOP().toString()}), notaFiscalTO);
                                }
                            } else if (produto.getCFOP().toString().startsWith("7")) {
                                TNFe.InfNFe.Exporta exporta = nfeDocument.getNFe().getInfNFe().getExporta();
                                if ((exporta == null) || (StringHelper.isBlankOrNull(exporta.getUFEmbarq())) || (StringHelper.isBlankOrNull(exporta.getXLocEmbarq()))) {
                                    adicionarErro(classNameDet + MessageFormat.format(HSMessageConstants.INFNFE_PRODSERV_CFOP_EXPORTACAO_LOCAL_EMBARQUE_INVALIDO, new Object[]{produto.getCFOP().toString()}), notaFiscalTO);
                                }
                                if ((det[i].getImposto() != null) && (det[i].getImposto().getICMS() != null)) {
                                    CSTICMS csticms = getCodigoICMS(det[i].getImposto().getICMS());
                                    String cst = "";
                                    if ((csticms != null) && (!StringHelper.isBlankOrNull(csticms.cst))) {
                                        cst = csticms.cst;
                                    }
                                    if ((!cst.equals(CSTEnum.X_41.getCST())) && (!cst.equals(CSOSNEnum.X_300.getCSOSN()))) {
                                        adicionarErro(classNameDet + HSMessageConstants.INFNFE_ITEMTRIB_CFOP_EXPORTACAO_ICMS_INCOMP, notaFiscalTO);
                                    }
                                }
                            }
                        }

                    }

                    if (imposto != null) {
                        if ((produto != null) && (imposto.getIPI() != null) && ((StringHelper.isBlankOrNull(produto.getNCM())) || (produto.getNCM().trim().length() != 8))) {
                            adicionarErro(classNameDet + HSMessageConstants.INFNFE_ITEMTRIB_IPI_REJEICAO_NCM, notaFiscalTO);
                        }

                        if (imposto.getICMS() != null) {
                            CSTICMS csticms = getCodigoICMS(det[i].getImposto().getICMS());
                            String cst = csticms.cst;
                            if (!StringHelper.isBlankOrNull(cst)) {
                                informadoGrupoICMS = true;
                            }
                            BigDecimal valorICMS = csticms.getVICMSDecimal();
                            BigDecimal aliquotaICMS = csticms.getPICMSDecimal();
                            BigDecimal baseCalculoICMS = csticms.getVBCDecimal();
                            BigDecimal baseCalculoICMSST = csticms.getBCSTDecimal();
                            BigDecimal valorICMSST = csticms.getVICMSSTDecimal();

                            if (((CSTEnum.X_00.getCST().equals(cst)) || (CSTEnum.X_10.getCST().equals(cst)) || (CSTEnum.X_20.getCST().equals(cst)) || (CSTEnum.X_51.getCST().equals(cst)) || (CSTEnum.X_70.getCST().equals(cst))) && (FinalidadeEmissaoEnum.NFE_NORMAL.getCodigo().equals(nfeDocument.getNFe().getInfNFe().getIde().getFinNFe().toString())) && (!StringHelper.isBlankOrNull(cst)) && (valorICMS != null) && (aliquotaICMS != null) && (baseCalculoICMS != null)) {
                                double diff = Math.abs(baseCalculoICMS.doubleValue() * aliquotaICMS.doubleValue() / 100.0D - valorICMS.doubleValue());
                                if (diff > DOUBLE_FORMAT) {
                                    adicionarErro(classNameDet + MessageFormat.format(HSMessageConstants.INFNFE_ITEMTRIB_VICMS_DIFER_VBC_PCIS, new Object[]{csticms.getVICMSDecimal(), csticms.getVBCDecimal(), csticms.getPICMSDecimal()}), notaFiscalTO);
                                }
                            }

                            if ((!CSTEnum.X_40.getCST().equals(cst)) && (!CSTEnum.X_41.getCST().equals(cst)) && (!CSTEnum.X_50.getCST().equals(cst)) && (!CSTEnum.X_51.getCST().equals(cst)) && (!CSTEnum.X_60.getCST().equals(cst)) && (!CSOSNEnum.X_101.getCSOSN().equals(cst)) && (!CSOSNEnum.X_102.getCSOSN().equals(cst)) && (!CSOSNEnum.X_103.getCSOSN().equals(cst)) && (!CSOSNEnum.X_300.getCSOSN().equals(cst)) && (!CSOSNEnum.X_300.getCSOSN().equals(cst)) && (!CSOSNEnum.X_500.getCSOSN().equals(cst))) {
                                if (baseCalculoICMS != null) {
                                    valorTotalBCICMS += baseCalculoICMS.doubleValue();
                                }
                                if (valorICMS != null) {
                                    valorTotalICMS += valorICMS.doubleValue();
                                }
                                if (baseCalculoICMSST != null) {
                                    valorTotalBCICMSST += baseCalculoICMSST.doubleValue();
                                }
                                if (valorICMSST != null) {
                                    valorTotalICMSST += valorICMSST.doubleValue();
                                }
                            }

                            if (emitente.getCRT() != null) {
                                if (CRTEnum.SN_1.getCRT().equals(emitente.getCRT().toString())) {
                                    if ((cst != null) && (Integer.parseInt(cst) <= 90)) {
                                        adicionarErro(classNameDet + HSMessageConstants.INFNFE_ITEMTRIB_INFORMADO_CST_PARA_EMISSOR_SIMPLES_NACIONAL, notaFiscalTO);
                                    }
                                } else if ((cst != null) && (Integer.parseInt(cst) > 90)) {
                                    adicionarErro(classNameDet + HSMessageConstants.INFNFE_ITEMTRIB_INFORMADO_CSOSN_PARA_EMISSOR_NAO_SIMPLES_NACIONAL, notaFiscalTO);
                                }
                            }
                        }

                        if (imposto.getISSQN() != null) {
                            informadoGrupoISSQN = true;
                            if ((emitente == null) || (StringHelper.isBlankOrNull(emitente.getIM()))) {
                                adicionarErro(classNameDet + HSMessageConstants.INFNFE_ITEMTRIB_ISSQN_SEM_IM, notaFiscalTO);
                            }
                        }

                        if ((imposto.getIPI() != null) && (imposto.getIPI().getIPITrib() != null) && (!StringHelper.isBlankOrNull(imposto.getIPI().getIPITrib().getVIPI()))) {
                            valorTotalIPI += new BigDecimal(imposto.getIPI().getIPITrib().getVIPI()).doubleValue();
                        }
                    }

                    if (produto == null) {
                        continue;
                    }
                    if ((!StringHelper.isBlankOrNull(produto.getVProd())) && (!StringHelper.isBlankOrNull(produto.getIndTot())) && (TNFe.InfNFe.Det.Prod.IndTot.X_1.equals(produto.getIndTot()))) {
                        valorTotalProduto += new BigDecimal(produto.getVProd()).doubleValue();
                    }
                    if (!StringHelper.isBlankOrNull(produto.getVFrete())) {
                        valorTotalFrete += new BigDecimal(produto.getVFrete()).doubleValue();
                    }
                    if (!StringHelper.isBlankOrNull(produto.getVSeg())) {
                        valorTotalSeguro += new BigDecimal(produto.getVSeg()).doubleValue();
                    }
                    if (!StringHelper.isBlankOrNull(produto.getVDesc())) {
                        valorTotalDesconto += new BigDecimal(produto.getVDesc()).doubleValue();
                    }
                }

                if ((informadoGrupoISSQN) && (!informadoGrupoICMS) && (!"DF".equals(notaFiscalTO.getEmitenteTO().getEnderEmit().getUF())));
                validarTotais(nfeDocument, valorTotalBCICMS, valorTotalICMS, valorTotalBCICMSST, valorTotalICMSST, valorTotalProduto, valorTotalFrete, valorTotalSeguro, valorTotalDesconto, valorTotalIPI, notaFiscalTO);
            }
        } catch (Exception ex) {
            throw new HSValidationException(ex.getMessage(), ex);
        }
    }

    /**
     * Valida os totais da NF-e.
     */
    private void validarTotais(NFeDocument nfeDocument, double valorBC, double valorTotalICMS, double valorTotalBCICMSST, double valorTotalICMSST, double valorTotalProduto, double valorTotalFrete, double valorTotalSeguro, double valorTotalDesconto, double valorTotalIPI, NotaFiscalTO notaFiscalTO) throws HSValidationException {
        TNFe.InfNFe.Total total = nfeDocument.getNFe().getInfNFe().getTotal();
        String classNameTotais = MessageFormat.format(HSConstants.APP_CLASS_NAME, new Object[]{"Total"});

        if (total.getICMSTot() != null) {
            if (compararValores(total.getICMSTot().getVBC(), valorBC, DOUBLE_FORMAT)) {
                adicionarErro(classNameTotais + MessageFormat.format(HSMessageConstants.INFNFE_TOTALNFE_VALOR_BC_INCONSISTENTE, new Object[]{StringHelper.formatarValor(total.getICMSTot().getVBC(), 2, 2), StringHelper.formatarValor(Double.valueOf(valorBC), 13, 2)}), notaFiscalTO);
            }
            if (compararValores(total.getICMSTot().getVICMS(), valorTotalICMS, DOUBLE_FORMAT)) {
                adicionarErro(classNameTotais + MessageFormat.format(HSMessageConstants.INFNFE_TOTALNFE_VALOR_ICMS_INCONSISTENTE, new Object[]{StringHelper.formatarValor(total.getICMSTot().getVICMS(), 2, 2), StringHelper.formatarValor(Double.valueOf(valorTotalICMS), 13, 2)}), notaFiscalTO);
            }
            if (compararValores(total.getICMSTot().getVBCST(), valorTotalBCICMSST, DOUBLE_FORMAT)) {
                adicionarErro(classNameTotais + MessageFormat.format(HSMessageConstants.INFNFE_TOTALNFE_VALOR_BCST_INCONSISTENTE, new Object[]{StringHelper.formatarValor(total.getICMSTot().getVBCST(), 2, 2), StringHelper.formatarValor(Double.valueOf(valorTotalBCICMSST), 13, 2)}), notaFiscalTO);
            }
            if (compararValores(total.getICMSTot().getVST(), valorTotalICMSST, DOUBLE_FORMAT)) {
                adicionarErro(classNameTotais + MessageFormat.format(HSMessageConstants.INFNFE_TOTALNFE_VALOR_ICMSST_INCONSISTENTE, new Object[]{StringHelper.formatarValor(total.getICMSTot().getVST(), 2, 2), StringHelper.formatarValor(Double.valueOf(valorTotalICMSST), 13, 2)}), notaFiscalTO);
            }
            if (compararValores(total.getICMSTot().getVProd(), valorTotalProduto, DOUBLE_FORMAT)) {
                adicionarErro(classNameTotais + MessageFormat.format(HSMessageConstants.INFNFE_TOTALNFE_VALOR_PRODUTOS_INCONSISTENTE, new Object[]{StringHelper.formatarValor(total.getICMSTot().getVProd(), 2, 2), StringHelper.formatarValor(Double.valueOf(valorTotalProduto), 13, 2)}), notaFiscalTO);
            }
            if (compararValores(total.getICMSTot().getVFrete(), valorTotalFrete, DOUBLE_FORMAT)) {
                adicionarErro(classNameTotais + MessageFormat.format(HSMessageConstants.INFNFE_TOTALNFE_VALOR_FRETE_INCONSISTENTE, new Object[]{StringHelper.formatarValor(total.getICMSTot().getVFrete(), 2, 2), StringHelper.formatarValor(Double.valueOf(valorTotalFrete), 13, 2)}), notaFiscalTO);
            }
            if (compararValores(total.getICMSTot().getVSeg(), valorTotalSeguro, DOUBLE_FORMAT)) {
                adicionarErro(classNameTotais + MessageFormat.format(HSMessageConstants.INFNFE_TOTALNFE_VALOR_SEGURO_INCONSISTENTE, new Object[]{StringHelper.formatarValor(total.getICMSTot().getVSeg(), 2, 2), StringHelper.formatarValor(Double.valueOf(valorTotalSeguro), 13, 2)}), notaFiscalTO);
            }
            if (compararValores(total.getICMSTot().getVDesc(), valorTotalDesconto, DOUBLE_FORMAT)) {
                adicionarErro(classNameTotais + MessageFormat.format(HSMessageConstants.INFNFE_TOTALNFE_VALOR_DESCONTO_INCONSISTENTE, new Object[]{StringHelper.formatarValor(total.getICMSTot().getVDesc(), 2, 2), StringHelper.formatarValor(Double.valueOf(valorTotalDesconto), 13, 2)}), notaFiscalTO);
            }
            if (compararValores(total.getICMSTot().getVIPI(), valorTotalIPI, DOUBLE_FORMAT)) {
                adicionarErro(classNameTotais + MessageFormat.format(HSMessageConstants.INFNFE_TOTALNFE_VALOR_IPI_INCONSISTENTE, new Object[]{StringHelper.formatarValor(total.getICMSTot().getVIPI(), 2, 2), StringHelper.formatarValor(Double.valueOf(valorTotalIPI), 13, 2)}), notaFiscalTO);
            }
        }
    }

    /**
     * Valida os transportes da NF-e.
     */
    private void validarTransporte(NFeDocument nfeDocument, NotaFiscalTO notaFiscalTO) throws HSValidationException {
        TNFe.InfNFe.Transp transporte = nfeDocument.getNFe().getInfNFe().getTransp();

        if ((transporte != null) && (notaFiscalTO.getTransporteTO() != null)) {
            validarAnotacoes(notaFiscalTO.getTransporteTO(), notaFiscalTO);
        }
    }

    /**
     * Obtém o código CST do ICMS.
     */
    private CSTICMS getCodigoICMS(TNFe.InfNFe.Det.Imposto.ICMS icms) {
        CSTICMS ctsIcms = new CSTICMS();
        if ((icms.getICMS00() != null) && (!StringHelper.isBlankOrNull(icms.getICMS00().getCST())) && (TNFe.InfNFe.Det.Imposto.ICMS.ICMS00.CST.X_00.equals(icms.getICMS00().getCST()))) {
            return new CSTICMS(CSTEnum.X_00.getCST(), icms.getICMS00().getVICMS(), icms.getICMS00().getPICMS(), icms.getICMS00().getVBC(), null, null, null);
        }
        if ((icms.getICMS10() != null) && (!StringHelper.isBlankOrNull(icms.getICMS10().getCST())) && (TNFe.InfNFe.Det.Imposto.ICMS.ICMS10.CST.X_10.equals(icms.getICMS10().getCST()))) {
            return new CSTICMS(CSTEnum.X_10.getCST(), icms.getICMS10().getVICMS(), icms.getICMS10().getPICMS(), icms.getICMS10().getVBC(), icms.getICMS10().getVBCST(), icms.getICMS10().getPICMSST(), icms.getICMS10().getVICMSST());
        }
        if ((icms.getICMS20() != null) && (!StringHelper.isBlankOrNull(icms.getICMS20().getCST())) && (TNFe.InfNFe.Det.Imposto.ICMS.ICMS20.CST.X_20.equals(icms.getICMS20().getCST()))) {
            return new CSTICMS(CSTEnum.X_20.getCST(), icms.getICMS20().getVICMS(), icms.getICMS20().getPICMS(), icms.getICMS20().getVBC(), null, null, null);
        }
        if ((icms.getICMS30() != null) && (!StringHelper.isBlankOrNull(icms.getICMS30().getCST())) && (TNFe.InfNFe.Det.Imposto.ICMS.ICMS30.CST.X_30.equals(icms.getICMS30().getCST()))) {
            return new CSTICMS(CSTEnum.X_30.getCST(), null, null, null, icms.getICMS30().getVBCST(), icms.getICMS30().getPICMSST(), icms.getICMS30().getVICMSST());
        }
        if ((icms.getICMS40() != null) && (!StringHelper.isBlankOrNull(icms.getICMS40().getCST()))) {
            if (TNFe.InfNFe.Det.Imposto.ICMS.ICMS40.CST.X_40.equals(icms.getICMS40().getCST())) {
                return new CSTICMS(CSTEnum.X_40.getCST(), icms.getICMS40().getVICMS(), null, null, null, null, null);
            }
            if (TNFe.InfNFe.Det.Imposto.ICMS.ICMS40.CST.X_41.equals(icms.getICMS40().getCST())) {
                return new CSTICMS(CSTEnum.X_41.getCST(), icms.getICMS40().getVICMS(), null, null, null, null, null);
            }
            if (TNFe.InfNFe.Det.Imposto.ICMS.ICMS40.CST.X_50.equals(icms.getICMS40().getCST())) {
                return new CSTICMS(CSTEnum.X_50.getCST(), icms.getICMS40().getVICMS(), null, null, null, null, null);
            }
        }
        if ((icms.getICMS51() != null) && (!StringHelper.isBlankOrNull(icms.getICMS51().getCST())) && (TNFe.InfNFe.Det.Imposto.ICMS.ICMS51.CST.X_51.equals(icms.getICMS51().getCST()))) {
            return new CSTICMS(CSTEnum.X_51.getCST(), icms.getICMS51().getVICMS(), icms.getICMS51().getPICMS(), icms.getICMS51().getVBC(), null, null, null);
        }
        if ((icms.getICMS60() != null) && (!StringHelper.isBlankOrNull(icms.getICMS60().getCST())) && (TNFe.InfNFe.Det.Imposto.ICMS.ICMS60.CST.X_60.equals(icms.getICMS60().getCST()))) {
            return new CSTICMS(CSTEnum.X_60.getCST(), null, null, null, null, null, null);
        }
        if ((icms.getICMS70() != null) && (!StringHelper.isBlankOrNull(icms.getICMS70().getCST())) && (TNFe.InfNFe.Det.Imposto.ICMS.ICMS70.CST.X_70.equals(icms.getICMS70().getCST()))) {
            return new CSTICMS(CSTEnum.X_70.getCST(), icms.getICMS70().getVICMS(), icms.getICMS70().getPICMS(), icms.getICMS70().getVBC(), icms.getICMS70().getVBCST(), icms.getICMS70().getPICMSST(), icms.getICMS70().getVICMSST());
        }
        if ((icms.getICMS90() != null) && (!StringHelper.isBlankOrNull(icms.getICMS90().getCST())) && (TNFe.InfNFe.Det.Imposto.ICMS.ICMS90.CST.X_90.equals(icms.getICMS90().getCST()))) {
            return new CSTICMS(CSTEnum.X_90.getCST(), icms.getICMS90().getVICMS(), icms.getICMS90().getPICMS(), icms.getICMS90().getVBC(), icms.getICMS90().getVBCST(), icms.getICMS90().getPICMSST(), icms.getICMS90().getVICMSST());
        }
        if ((icms.getICMSPart() != null) && (!StringHelper.isBlankOrNull(icms.getICMSPart().getCST()))) {
            if (TNFe.InfNFe.Det.Imposto.ICMS.ICMSPart.CST.X_10.equals(icms.getICMSPart().getCST())) {
                return new CSTICMS(CSTEnum.X_10_Part.getCST(), icms.getICMSPart().getVICMS(), icms.getICMSPart().getPICMS(), icms.getICMSPart().getVBC(), icms.getICMSPart().getVBCST(), icms.getICMSPart().getPICMSST(), icms.getICMSPart().getVICMSST());
            }
            if (TNFe.InfNFe.Det.Imposto.ICMS.ICMSPart.CST.X_90.equals(icms.getICMSPart().getCST())) {
                return new CSTICMS(CSTEnum.X_90_Part.getCST(), icms.getICMSPart().getVICMS(), icms.getICMSPart().getPICMS(), icms.getICMSPart().getVBC(), icms.getICMSPart().getVBCST(), icms.getICMSPart().getPICMSST(), icms.getICMSPart().getVICMSST());
            }
        }
        if ((icms.getICMSSN101() != null) && (!StringHelper.isBlankOrNull(icms.getICMSSN101().getCSOSN())) && (TNFe.InfNFe.Det.Imposto.ICMS.ICMSSN101.CSOSN.X_101.equals(icms.getICMSSN101().getCSOSN()))) {
            return new CSTICMS(CSOSNEnum.X_101.getCSOSN(), null, null, null, null, null, null);
        }
        if ((icms.getICMSSN102() != null) && (!StringHelper.isBlankOrNull(icms.getICMSSN102().getCSOSN()))) {
            if (TNFe.InfNFe.Det.Imposto.ICMS.ICMSSN102.CSOSN.X_102.equals(icms.getICMSSN102().getCSOSN())) {
                return new CSTICMS(CSOSNEnum.X_102.getCSOSN(), null, null, null, null, null, null);
            }
            if (TNFe.InfNFe.Det.Imposto.ICMS.ICMSSN102.CSOSN.X_300.equals(icms.getICMSSN102().getCSOSN())) {
                return new CSTICMS(CSOSNEnum.X_300.getCSOSN(), null, null, null, null, null, null);
            }
            if (TNFe.InfNFe.Det.Imposto.ICMS.ICMSSN102.CSOSN.X_103.equals(icms.getICMSSN102().getCSOSN())) {
                return new CSTICMS(CSOSNEnum.X_103.getCSOSN(), null, null, null, null, null, null);
            }
            if (TNFe.InfNFe.Det.Imposto.ICMS.ICMSSN102.CSOSN.X_400.equals(icms.getICMSSN102().getCSOSN())) {
                return new CSTICMS(CSOSNEnum.X_400.getCSOSN(), null, null, null, null, null, null);
            }
        }
        if ((icms.getICMSSN201() != null) && (!StringHelper.isBlankOrNull(icms.getICMSSN201().getCSOSN())) && (TNFe.InfNFe.Det.Imposto.ICMS.ICMSSN201.CSOSN.X_201.equals(icms.getICMSSN201().getCSOSN()))) {
            return new CSTICMS(CSOSNEnum.X_201.getCSOSN(), null, null, null, icms.getICMSSN201().getVBCST(), icms.getICMSSN201().getPICMSST(), icms.getICMSSN201().getVICMSST());
        }
        if ((icms.getICMSSN202() != null) && (!StringHelper.isBlankOrNull(icms.getICMSSN202().getCSOSN()))) {
            if (TNFe.InfNFe.Det.Imposto.ICMS.ICMSSN202.CSOSN.X_202.equals(icms.getICMSSN202().getCSOSN())) {
                return new CSTICMS(CSOSNEnum.X_202.getCSOSN(), null, null, null, icms.getICMSSN202().getVBCST(), icms.getICMSSN202().getPICMSST(), icms.getICMSSN202().getVICMSST());
            }
            if (TNFe.InfNFe.Det.Imposto.ICMS.ICMSSN202.CSOSN.X_203.equals(icms.getICMSSN202().getCSOSN())) {
                return new CSTICMS(CSOSNEnum.X_203.getCSOSN(), null, null, null, icms.getICMSSN202().getVBCST(), icms.getICMSSN202().getPICMSST(), icms.getICMSSN202().getVICMSST());
            }
        }
        if ((icms.getICMSSN500() != null) && (!StringHelper.isBlankOrNull(icms.getICMSSN500().getCSOSN())) && (TNFe.InfNFe.Det.Imposto.ICMS.ICMSSN500.CSOSN.X_500.equals(icms.getICMSSN500().getCSOSN()))) {
            return new CSTICMS(CSOSNEnum.X_500.getCSOSN(), null, null, null, null, null, null);
        }
        if ((icms.getICMSSN900() != null) && (!StringHelper.isBlankOrNull(icms.getICMSSN900().getCSOSN())) && (TNFe.InfNFe.Det.Imposto.ICMS.ICMSSN900.CSOSN.X_900.equals(icms.getICMSSN900().getCSOSN()))) {
            return new CSTICMS(CSOSNEnum.X_900.getCSOSN(), icms.getICMSSN900().getVICMS(), icms.getICMSSN900().getPICMS(), icms.getICMSSN900().getVBC(), icms.getICMSSN900().getVBCST(), icms.getICMSSN900().getPICMSST(), icms.getICMSSN900().getVICMSST());
        }
        if ((icms.getICMSST() != null) && (!StringHelper.isBlankOrNull(icms.getICMSST().getCST()))) {
            return new CSTICMS(CSTEnum.X_41.getCST(), null, null, null, null, null, null);
        }
        return ctsIcms;
    }

    /**
     * Compara dois valores
     */
    private boolean compararValores(String valor1, double valor2, double tolerancia) {
        boolean result = true;
        if ((StringHelper.isBlankOrNull(valor1)) && (valor2 > 0.0D)) {
            result = true;
        } else if ((StringHelper.isBlankOrNull(valor1)) && (valor2 == 0.0D)) {
            result = false;
        } else {
            double diff = Math.abs(new BigDecimal(valor1).doubleValue() - valor2);
            if (diff > tolerancia) {
                result = true;
            } else {
                result = false;
            }
        }
        return result;
    }

    /**
     * Adiciona um erro a nota fiscal.
     */
    private void adicionarErro(String error, NotaFiscalTO notaFiscalTO) {
        if (error.startsWith("[")) {
            int index = className.lastIndexOf("]");
            error = className.substring(0, index) + "/" + error.substring(1);
        } else {
            error = className + error;
        }
        notaFiscalTO.addValidationError(error);
    }

    /**
     * Obtém o nome da classe pela anotação.
     */
    private String getClassName(Class clazz) {
        return MessageFormat.format(HSConstants.APP_CLASS_NAME, new Object[]{((Node) clazz.getAnnotation(Node.class)).name()});
    }

    /**
     * Valida as anotações da classe.
     */
    private void validarAnotacoes(BaseTO baseTO, NotaFiscalTO notaFiscalTO) throws HSValidationException {
        try {
            if ((baseTO != null) && (baseTO instanceof Validable)) {
                Validable validabble = (Validable) baseTO.clone();
                ValidadorAnotacoes.validate(validabble);
                baseTO = (BaseTO) validabble;
                if (baseTO.hasValidationError()) {
                    for (String error : baseTO.getValidationErrorList()) {
                        adicionarErro(error, notaFiscalTO);
                    }
                }
            }
        } catch (CloneNotSupportedException ex) {
            throw new HSValidationException(ex.getMessage(), ex);
        }
    }

    /**
     * Classe interna para armazenagem dos valores do ICMS.
     */
    private class CSTICMS {

        String cst;
        String vICMS;
        String pICMS;
        String vBC;
        String vBCST;
        String pICMSST;
        String vICMSST;

        CSTICMS() {
        }

        CSTICMS(String cst, String vICMS, String pICMS, String vBC, String vBCST, String pICMSST, String vICMSST) {
            this.cst = cst;
            this.vICMS = vICMS;
            this.pICMS = pICMS;
            this.vBC = vBC;
            this.vBCST = vBCST;
            this.pICMSST = pICMSST;
            this.vICMSST = vICMSST;
        }

        BigDecimal getVICMSDecimal() {
            BigDecimal result = null;
            if (!StringHelper.isBlankOrNull(vICMS)) {
                result = new BigDecimal(vICMS);
            }
            return result;
        }

        BigDecimal getPICMSDecimal() {
            BigDecimal result = null;
            if (!StringHelper.isBlankOrNull(pICMS)) {
                result = new BigDecimal(pICMS);
            }
            return result;
        }

        BigDecimal getVBCDecimal() {
            BigDecimal result = null;
            if (!StringHelper.isBlankOrNull(vBC)) {
                result = new BigDecimal(vBC);
            }
            return result;
        }

        BigDecimal getBCSTDecimal() {
            BigDecimal result = null;
            if (!StringHelper.isBlankOrNull(vBCST)) {
                result = new BigDecimal(vBCST);
            }
            return result;
        }

        BigDecimal getPICMSSTDecimal() {
            BigDecimal result = null;
            if (!StringHelper.isBlankOrNull(pICMSST)) {
                result = new BigDecimal(pICMSST);
            }
            return result;
        }

        BigDecimal getVICMSSTDecimal() {
            BigDecimal result = null;
            if (!StringHelper.isBlankOrNull(vICMSST)) {
                result = new BigDecimal(vICMSST);
            }
            return result;
        }

        String getVICMSString() {
            String result = null;
            if (!StringHelper.isBlankOrNull(vICMS)) {
                result = StringHelper.formatarValor(vICMS, 13, 2);
            }
            return result;
        }

        String getPICMSString() {
            String result = null;
            if (!StringHelper.isBlankOrNull(pICMS)) {
                result = StringHelper.formatarValor(pICMS, 3, 2);
            }
            return result;
        }

        String getVBCString() {
            String result = null;
            if (!StringHelper.isBlankOrNull(vBC)) {
                result = StringHelper.formatarValor(vBC, 13, 2);
            }
            return result;
        }

        String getBCSTString() {
            String result = null;
            if (!StringHelper.isBlankOrNull(vBCST)) {
                result = StringHelper.formatarValor(vBCST, 13, 2);
            }
            return result;
        }

        String getPICMSSTString() {
            String result = null;
            if (!StringHelper.isBlankOrNull(pICMSST)) {
                result = StringHelper.formatarValor(pICMSST, 3, 2);
            }
            return result;
        }

        String getVICMSSTString() {
            String result = null;
            if (!StringHelper.isBlankOrNull(vICMSST)) {
                result = StringHelper.formatarValor(vICMSST, 13, 2);
            }
            return result;
        }
    }
}
